import matplotlib
import numpy as np
import matplotlib.pyplot as plt

# ---------- 1. 基础数据 ----------
# 控制点（每个点是 (x,y)）
P = np.array([[1., 0.],
              [2., 3.],
              [3.,-1.],
              [4., 5.]])

# 参数取值范围
u = np.linspace(0., 1., 200)   # 采样 200 个点，使曲线平滑

# ---------- 2. Catmull‑Rom 基矩阵（含张力 τ） ----------
def catmull_rom_matrix(tau):
    """返回 4×4 基矩阵 M(τ)"""
    return np.array([[0.,          1.,          0.,          0.],
                     [-tau,        0.,          tau,         0.],
                     [2*tau,       tau-3.,      3-2*tau,    -tau],
                     [-tau,        2.-tau,      tau-2.,      tau]])

# ---------- 3. 计算曲线点 ----------
def catmull_rom_curve(tau, u_vals):
    """给定 τ 与参数向量 u，返回曲线上的 (x,y) 列表"""
    M = catmull_rom_matrix(tau)          # 4×4 基矩阵
    # 参数向量 1×4
    U = np.vstack([np.ones_like(u_vals), u_vals, u_vals**2, u_vals**3]).T   # (N,4)
    # 计算系数 C = U·M   (N,4)
    C = U @ M
    # 曲线点 = C·P   (N,2)
    pts = C @ P
    return pts[:,0], pts[:,1]   # x, y

# ---------- 4. 绘图 ----------
if __name__ == "__main__":
    matplotlib.rcParams['font.family'] = 'Microsoft YaHei'  # Windows 常用

    taus = [-1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5]
    colors = plt.cm.viridis(np.linspace(0, 1, len(taus)))

    plt.figure(figsize=(8,5))
    # 绘制控制点（所有 τ 共用同一组点）
    plt.plot(P[:,0], P[:,1], 'ko', label='控制点')

    for tau, col in zip(taus, colors):
        x, y = catmull_rom_curve(tau, u)
        plt.plot(x, y, color=col, lw=2,
                 label=r'$\tau={}$'.format(tau))

    plt.title('Catmull Rom 样条（不同张力 τ）')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.grid(True, linestyle='--', alpha=0.6)
    plt.legend()
    plt.tight_layout()
    plt.show()
